﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;

using Game.Global.Buffer;
using Game.CellSimulator.Data;

namespace Game
{
	public class SimulatorController : MonoBehaviour 
	{
        GameMode m_gameMode = GameMode.Mission;

        /// <summary>
        /// 计算细胞状态的Table
        /// </summary>
        Table m_cellTableData;

        
        /// <summary>
        /// Table的视图表现（用于放置细胞）
        /// </summary>
        Transform m_cellTableTransform;
        
        
        /// <summary>
        /// 棋盘边长（Data/View）
        /// </summary>
        [SerializeField]int m_tableLength= 10;

        /// <summary>
        /// 持续的回合，每次修改则将导致重置
        /// </summary>
        int m_roundsCount = 0;

        /// <summary>
        /// 目标细胞数，达到即为过关
        /// </summary>
        [SerializeField]
        int m_targetCells = 20;

        /// <summary>
        /// 可用的细胞（如果不足则不允许再使用）
        /// </summary>
        [SerializeField]int m_usableCells = 10;
        
        /// <summary>
        /// 最多允许回合数
        /// </summary>
        [SerializeField]int m_maxRoundsAllowed = 5;

        /// <summary>
        /// 关卡序号
        /// </summary>
        [SerializeField] int m_missionIndex;

        /// <summary>
        /// 是否允许删除细胞
        /// </summary>
        bool m_allowRemoveCell = true;

		void Start () 
		{
            //TODO 放到View中：初始化视图需要的数据
            //m_cellObjsBuffer = new GameObjBuffer(m_cellPrefab, 1000);
            //边长

            //--初始化视图：
            CellsView m_cellTableView = CellsView.instance;
            m_cellTableTransform = m_cellTableView.transform;
            m_cellTableView.Init(m_tableLength);

            //--初始化镜头
            m_mainCamera = Camera.main;
            m_currViewSize = m_mainCamera.orthographicSize;
            
            //--设置镜头大小
            SetCameraView(m_tableLength);

            //初始化Data层行为：：
            //--Table更新时候的操作：将视图绑定到Data上
            m_cellTableData = new Table(m_tableLength,
                //Callback: A cell Born
                m_cellTableView.PutCellObjAt,

                //Callback: A cell die
                m_cellTableView.ClearCellObjAt,

                //Callback: All cells updated
                //防止更新过快跟不上刷新
                OnTableUpdateEnd
                );

            //m_cellTableData.TestInitTable(tableLength);

            //初始化 UI 按钮事件：
            InitUI();

            //Button [Menu]
            MyInput.SetButtonFunction("MenuButton", SwitchMenu);

            //Button [Next]
            MyInput.SetButtonFunction("NextButton", DoNext);

            //Button [Clear]
            MyInput.SetButtonFunction("ClearButton", Clear);

            //Button [Replay]
            MyInput.SetButtonFunction("ReplayButton", Replay);

		}

        RaycastHit hitInfo;                         //临时变量：按到棋盘与否
        bool m_isMouseDoubleClicking = false;       //鼠标是否是双击后的拖拽（擦除事件判定）
        bool m_isMouseOperatingUI = false;          //标记鼠标是否正在操作UI（如拖拽摇杆，则不应该进行点击处理）
		void Update () 
		{
            //PC TEST
#if UNITY_EDITOR || UNITY_STANDALONE
            if (Input.GetKeyUp(KeyCode.Space)
                && CanUpdateTable())
            {
                DoNext();

            }
            else if (Input.GetKeyUp(KeyCode.C))
            {
                Clear();
            }
            else if (Input.GetKeyDown(KeyCode.R))
            {
                Debug.Log("Will save this map as mission:");
                GameMission mission = new GameMission();
                mission.cellsList = new List<IntVector2>(m_cellTableData.m_aliveCellsSet);
                mission.roundsAllowed = m_maxRoundsAllowed;
                mission.targetCells = m_targetCells;
                mission.usableCells = m_usableCells;
                mission.tableLength = m_tableLength;

                MissionProvider.SaveMission(mission, m_missionIndex);
            }
            else if (Input.GetKeyDown(KeyCode.L))
            {
                Debug.Log("Will Load map at " + m_missionIndex);

                GameMission mission = MissionProvider.ReadMission(m_missionIndex);

                Debug.Log("Mission start with cells x" + mission.cellsList.Count ) ;

                //清除Cells数据（同时清除Cells视图）
                Clear();

                //重置棋盘格视图：TODO 这里可能出错，或者清除视图的操作还可以拆分？？？
                CellsView.instance.ResetView(mission.tableLength);

                //重新装入Cells：
                m_cellTableData.InitCells(mission.cellsList);

                //重置Camera
                SetCameraView(mission.tableLength);
                

            }
#endif
            //FOR mobile:

            //Not on ui, generate or score view:
            if ( !MyInput.IsMouseOnUI() && !m_isMouseOperatingUI )
            {
                #region Action
                //判断出鼠标动作是单点还是双击
                if (MyInput.GetMouseDoubleHold())
                {
                    Debug.Log("Double hold");
                    m_isMouseDoubleClicking = true;
                }
                else if (MyInput.GetMouseUp() && m_isMouseDoubleClicking)
                {
                    m_isMouseDoubleClicking = false;
                }

                //在鼠标按下的时候：
                if (MyInput.GetMouse()
                    && MyInput.IsMouseOnObj(out hitInfo)
                    && hitInfo.transform == m_cellTableTransform)
                {
                    //We will put a cell here:
                    Vector3 clickPos = hitInfo.point;
                    IntVector2 targetPos = new IntVector2();
                    targetPos.x = (int)clickPos.x;
                    targetPos.y = (int)clickPos.z;

                    //Put or remove:
                    if (m_isMouseDoubleClicking)
                    {
                        if (CanRemoveCell())
                        {
                            m_cellTableData.RemoveCellAt(targetPos);
                        }
                    }
                    else if(MyInput.touchCount ==1)
                    {
                        //如果能放置且成功放置该细胞
                        if (CanPutCell()
                            &&m_cellTableData.PutCellAt(targetPos)
                            )
                        {
                            //--可用的细胞将减少
                            m_usableCells--;

                            RefreshText();
                        }
                    }
                }



                #endregion
            }

            //Move view or scale view

            //对视图放大缩小/移动
            DoCameraAction();
        }

		//---------------------------------------------------------------------------
		//				Public area
		//---------------------------------------------------------------------------
		#region Public area
		#endregion

		//---------------------------------------------------------------------------
		//				Private area
		//---------------------------------------------------------------------------
		#region Private area

        /// <summary>
        /// 是否有可以放置的细胞
        /// </summary>
        /// <returns></returns>
        private bool CanPutCell()
        {
            if (m_usableCells <= 0)
            {
                Debug.Log("You cannot put Cell.");
                return false;
            }
            else
            {
                return true;
            }
        }

        /// <summary>
        /// 当前是否可以移除细胞
        /// </summary>
        private bool CanRemoveCell()
        {
            if (!m_allowRemoveCell)
            {
                Debug.Log("You cannot remove Cell.");
                return false;
            }

            return true;
        }


        bool m_isTableLocked = false;
        /// <summary>
        /// 当细胞图更新结束时调用
        /// </summary>
        private void OnTableUpdateEnd()
        {
            m_isTableLocked = false;
        }

        /// <summary>
        /// 当细胞图更新开始时调用
        /// </summary>
        private void OnTableUpdateStart()
        {
            m_isTableLocked = true;
        }

        private bool CanUpdateTable()
        {
            return !m_isTableLocked;
        }


        //镜头操作
        #region Camera
        Camera m_mainCamera;
        [SerializeField]
        float m_cameraMinSize;
        [SerializeField]
        float m_cameraMaxSize;
        float m_currViewSize;
        float m_scaleViewSize;
        Vector2 m_moveAxis;
        /// <summary>
        /// 对镜头进行移动、缩放操作
        /// </summary>
        private void DoCameraAction()
        {
            //缩放镜头
            if (MyInput.HasScrollViewOp(out m_scaleViewSize))
            {
                //计算镜头大小
                m_currViewSize = m_mainCamera.orthographicSize;
                m_currViewSize = m_currViewSize - m_scaleViewSize * Time.deltaTime * 10;
                m_currViewSize = Mathf.Clamp(m_currViewSize, m_cameraMinSize, m_cameraMaxSize);

                m_mainCamera.orthographicSize = m_currViewSize;
            }


            //移动镜头
            if (MyInput.IsAnyAxisChange())
            {
                m_moveAxis = MyInput.GetMoveAxis();

                m_mainCamera.transform.Translate(m_moveAxis * Time.deltaTime * m_currViewSize);

                m_isMouseOperatingUI = true;
            }
            else if (MyInput.GetMouseUp())  //不再操作摇杆了，则可以操作视图了
            {
                m_isMouseOperatingUI = false;
            }
        }


        /// <summary>
        /// 设置镜头的视野范围
        /// </summary>
        /// <param name="tableLength"></param>
        private void SetCameraView(int tableLength)
        {
            //--重置镜头到中心点，且镜头视野为棋盘大小+1
            m_mainCamera.transform.position = new Vector3(tableLength * 0.5f, tableLength, tableLength * 0.5f);
            m_mainCamera.orthographicSize = tableLength * 0.5f + 1;
        }

        #endregion

        #region UI function Part

        [SerializeField]Canvas m_gameUI;

        Text m_uiUsableCells;
        Text m_uiRoundsCount;
        private void InitUI()
        {
            m_uiUsableCells = m_gameUI.transform.GetChildByName<Text>("UsableCellsText");
            m_uiRoundsCount = m_gameUI.transform.GetChildByName<Text>("RoundsKeptText");

            //--缩放镜头的操作
            float cameraRange = m_cameraMaxSize - m_cameraMinSize;
            Slider viewScrollSlider = MyInput.GetUIObject<Slider>("ViewScrollSlider");
            viewScrollSlider.wholeNumbers = false;
            viewScrollSlider.minValue = 0f;
            viewScrollSlider.maxValue = 1f;
            viewScrollSlider.onValueChanged.AddListener(
                (val) =>
                {
                    //m_mainCamera.orthographicSize = val;
                    m_mainCamera.orthographicSize = val * cameraRange + m_cameraMinSize;
                    //--10~90 倒置算法：
                    //--80差值，
                });
            viewScrollSlider.value = 1f - (m_currViewSize - m_cameraMinSize) / cameraRange;
        }

        private void RefreshText()
        {
            m_uiUsableCells.text = "可用细胞 x"+m_usableCells;
            m_uiRoundsCount.text = "持续回合 x" + m_roundsCount;
        }

        private void Replay()
        {
            Debug.Log("replay>");
        }

        private void Clear()
        {
            m_cellTableData.ClearAllCellDatas();
            Debug.Log("Datas & view Clear");
        }

        [SerializeField]RectTransform m_menuPanel;
        private void SwitchMenu()
        {
            Debug.Log("Show/Hide menu");
            if(m_menuPanel.gameObject.activeInHierarchy)
                m_menuPanel.gameObject.SetActive(false);
            else
                m_menuPanel.gameObject.SetActive(true);
        }

        private void DoNext()
        {
            OnTableUpdateStart();
            Debug.Log("Round start...");

            //--TODO 先hash一次当前状态

            //调用数据层的更新：如果成功更新了，才能对回合+1
            StartCoroutine(m_cellTableData.UpdateCells());

            //--TODO 再hash当前状态，比对。如果成功更新了，才能对回合+1
        }

        #endregion

        #region type define
        private enum GameMode
        {
            /// <summary>
            /// 任务模式（每一关固定大小、固定生成的东西），有目标回合数目/目标数量
            /// </summary>
            Mission,

            /// <summary>
            /// 创造模式（100x100、自动Next、创造出100回合以上的稳定的结构（以最近更改，比如演化到一半，又添加了物体，则以此为准）），每次创造出来的如果是可自治的模式（但不能与之前完成的模式相同），则计入一种；
            /// </summary>
            GodCreator,

            ///// <summary>
            ///// 猜模式：随机一个生态系统，给出答案（是否能撑过50个回合）并验证（不能添加、删除）
            ///// </summary>
            ////GuessAndTry,


            /// <summary>
            /// 采蘑菇模式：不断地采摘认为多余的部分直到游戏在N个回合内结束且达到X个蘑菇及以上；
            /// </summary>
            HarvestMode,
        }
        #endregion

        #endregion
    }


}